
//网络连接初始化
void internet_setup(){
  WiFi.disconnect(true, false);      //关闭wifi功能
  if(system_internet_mode==1 && wifi_ssid.length()>0){
    mqtt_init();
  }else if(system_internet_mode==2 && wifi_ssid.length()>0){
    blinker_init();
  }
}
//循环，统一调用
void networkController(){
  //uart
  send2UART();
  receive_UART();
  //网络loop
  if(system_set_internet==1){           //配网
    if(system_set_initialized == 0){
      internet_settings_init();
      system_set_initialized = 1;
    }
    setting_server.handleClient();
  }else{
    //MQTT
    if(system_internet_mode==1){
      if(mqtt_client.connected()) {
        mqtt_client.loop();
        mqtt_heartbeat();
      }else{
        mqtt_reconnect();
      }
    }
    //blinker
    else if(system_internet_mode==2){
      Blinker.run();
    }
    //OTA
    if(system_internet_mode!=0 && system_enable_OTA==1){
      if(system_ota_initialized == 0){
        OTA_setup();
      }
      update_server.handleClient();
    }
  }
}

//1s计时器
bool internet_after_1s(){
  if(millis()-system_millis_last_internet>=1000){
    system_millis_last_internet = millis();
    return true;
  }else{
    return false;
  }
}
//输出信息到串口
void send2UART(){
  if(system_uart_print_state==1 && internet_after_1s()){
    //打印错误信息
    Serial.println();
    Serial.println(getSysInfo());
    
    //打印电流电压
    Serial.print(F("电压 1:   "));
    Serial.print(system_ina_voltage_1, 5);
    Serial.print(F(" V    "));
    Serial.print(F("电流 1:     "));
    Serial.print(system_ina_current_1, 5);
    Serial.print(F(" A    "));
    Serial.print(F("功率 1: "));
    Serial.print(system_ina_power_1, 5);
    Serial.print(F(" W    "));
    
    Serial.print(F("电压 2:   "));
    Serial.print(system_ina_voltage_2, 5);
    Serial.print(F(" V    "));
    Serial.print(F("电流 2:     "));
    Serial.print(system_ina_current_2, 5);
    Serial.print(F(" A    "));
    Serial.print(F("功率 2: "));
    Serial.print(system_ina_power_2, 5);
    Serial.print(F(" W    "));

    Serial.print(F("电压 3:   "));
    Serial.print(system_ina_voltage_3, 5);
    Serial.print(F(" V    "));
    Serial.print(F("电流 3:     "));
    Serial.print(system_ina_current_3, 5);
    Serial.print(F(" A    "));
    Serial.print(F("功率 3: "));
    Serial.print(system_ina_power_3, 5);
    Serial.print(F(" W    "));

    Serial.print(F("电池电量:   "));
    Serial.print(system_battery_percent);
    Serial.print(F(" %    "));

    Serial.print(F("电表:   "));
    Serial.print(system_power_meter_in);
    Serial.print(F(" Wh    "));
    Serial.print(system_power_meter_bat);
    Serial.print(F(" Wh    "));
    Serial.print(system_power_meter_out);
    Serial.print(F(" Wh    "));
    
    Serial.print(F("网络:   "));
    Serial.print(WiFi.status());

    Serial.println("");
  }
}

//接收串口数据
void receive_UART(){
  if(Serial.available()>0){
    delay(100); //等待数据接收完
    String readbuffer = Serial.readStringUntil(':');
    //处理数据
    Serial.println(readbuffer);
    //设置采样电阻阻值
    float readf = 0.0;
    if(readbuffer.compareTo("SSR1")==0){
      readf = Serial.parseFloat();
      if(readf>0.0){
        system_ina_resistor_1 = readf;
        SaveSettings();
        ESP.restart();
      }
    }else if(readbuffer.compareTo("SSR2")==0){
      readf = Serial.parseFloat();
      if(readf>0.0){
        system_ina_resistor_2 = readf;
        SaveSettings();
        ESP.restart();
      }
    }else if(readbuffer.compareTo("SSR3")==0){
      readf = Serial.parseFloat();
     if(readf>0.0){
        system_ina_resistor_3 = readf;
        SaveSettings();
        ESP.restart();
      }
    //历史电量数据清零
    }else if(readbuffer.compareTo("RESET")==0){
      int int_temp = Serial.parseInt();
      if(int_temp == 320){
        store_in_kwh             = 0.0;
        store_bat_kwh            = 0.0;
        store_out_kwh            = 0.0;
        system_power_meter_in    = 0.0;
        system_power_meter_bat   = 0.0;
        system_power_meter_out   = 0.0;
        store_sys_data();
      }
    }
    //清空缓存
    while(Serial.read()>=0){};
  }
}

const char* PROGMEM internet_setting_web = 
              "<html>"
              "<head>"
              "<meta charset=\"utf-8\">"
              "<title style=\"text-align:center\">网络配置</title>"
              "</head>"
              "<body>"
              "    <h1 style=\"text-align:center\">网络配置</h1>"
              "    <center>"
              "    <form id=\"internetsettings\" name=\"internetsettings\" method=\"Post\" action=\"/SET\">"
              "     <h2 style=\"text-align:center\">WIFI配置</h2>"
              "      名称: <input type=\"text\" name=\"ssid\"><br>"
              "      密码: <input type=\"password\" name=\"wifikey\"><br>"
              "        <h2 style=\"text-align:center\">Blinker配置</h2>"
              "      密钥: <input type=\"text\" name=\"blinkerkey\"><br>"
              "        <h2 style=\"text-align:center\">MQTT配置</h2>"
              "      地址: <input type=\"text\" name=\"mqttadd\"><br>"
              "      端口: <input type=\"number\" name=\"mqttport\"><br>"
              "      用户: <input type=\"text\" name=\"mqttusr\"><br>"
              "      密码: <input type=\"password\" name=\"mqttkey\"><br>"
              "        <h2 style=\"text-align:center\">OTA账户配置</h2>"
              "      账户: <input type=\"text\" name=\"otausr\"><br>"
              "      密码: <input type=\"password\" name=\"otapsd\"><br><br>"
              "        <input type=\"submit\" name=\"upload\" id=\"upload\" >"
              "    </form>"
              "  </center>"
              "</body>"
              "</html>";
//配网服务
void internet_settings_init(){
  //wifi转为AP模式
  while(!WiFi.softAP(settings_ap_ssid.c_str(), settings_ap_psd.c_str())){};
  Serial.println("AP:" + settings_ap_ssid + "  密码:" + settings_ap_psd);
  setting_server.on("/", HTTP_GET, []() {
    setting_server.sendHeader("Connection", "close");
    setting_server.send(200, "text/html", internet_setting_web);
  });
  setting_server.on("/SET", HTTP_POST, []() {
    if(setting_server.hasArg("ssid")&&setting_server.hasArg("otapsd")){
      //读取表单
      String wifi_ssid_readarg            = setting_server.arg("ssid");
      String wifi_psd_readarg             = setting_server.arg("wifikey");
      String blinker_auth_readarg         = setting_server.arg("blinkerkey");
      String mqtt_server_add_readarg      = setting_server.arg("mqttadd");
      String mqtt_server_port_readarg     = setting_server.arg("mqttport");
      String mqtt_usr_readarg             = setting_server.arg("mqttusr");
      String mqtt_psd_readarg             = setting_server.arg("mqttkey");
      String system_ota_usr_readarg       = setting_server.arg("otausr");
      String system_ota_psd_readarg       = setting_server.arg("otapsd");
      //去除空格
      wifi_ssid_readarg.trim();
      wifi_psd_readarg.trim();
      blinker_auth_readarg.trim();
      mqtt_server_add_readarg.trim();
      mqtt_server_port_readarg.trim();
      mqtt_usr_readarg.trim();
      mqtt_psd_readarg.trim();
      system_ota_usr_readarg.trim();
      system_ota_psd_readarg.trim();
      //判断是否有效
      if(wifi_ssid_readarg.length()>0){
        wifi_ssid = wifi_ssid_readarg;
      }
      if(wifi_psd_readarg.length()>0){
        wifi_psd = wifi_psd_readarg;
      }
      if(blinker_auth_readarg.length()>0){
        blinker_auth = blinker_auth_readarg;
      }
      if(mqtt_server_add_readarg.length()>0){
        mqtt_server_add = mqtt_server_add_readarg;
      }
      if(mqtt_server_port_readarg.length()>0&&atoi(mqtt_server_port_readarg.c_str()) < 65536){     //端口号范围0-65535
         mqtt_server_port = atoi(mqtt_server_port_readarg.c_str());
      }
      if(mqtt_usr_readarg.length()>0){
        mqtt_usr = mqtt_usr_readarg;
      }
      if(mqtt_psd_readarg.length()>0){
        mqtt_psd = mqtt_psd_readarg;
      }
      if(system_ota_usr_readarg.length()>0){
        system_ota_usr = system_ota_usr_readarg;
      }
      if(system_ota_psd_readarg.length()>0){
        system_ota_psd = system_ota_psd_readarg;
      }
      //保存设置
      SaveSettings();
      setting_server.send(200, "text/html", "<html><head><meta charset=\"utf-8\"><title>配置成功</title></head><body><h1 style=\"text-align:center\">配置成功，设备正在重新启动...请关闭网页!</h1></body></html>");
      delay(1000);
      ESP.restart();
    }
    
  });
  setting_server.begin();
  Serial.println(F("配网服务已启动!"));
}

/*
Blinker
以下是blinker代码部分
*/
//Blinker初始化
void blinker_init(){
  BLINKER_DEBUG.stream(Serial);
  char b_au[blinker_auth.length()+1];
  for(int i=0;i<=blinker_auth.length();i++){
    b_au[i] = blinker_auth.c_str()[i];
  }
  char b_ssid[wifi_ssid.length()+1];
  for(int i=0;i<=wifi_ssid.length();i++){
    b_ssid[i] = wifi_ssid.c_str()[i];
  }
  char b_psd[wifi_psd.length()+1];
  for(int i=0;i<=wifi_psd.length();i++){
    b_psd[i] = wifi_psd.c_str()[i];
  }
  Blinker.begin(b_au, b_ssid, b_psd);
  Blinker.attachData(blinker_dataRead);
  Blinker.attachHeartbeat(blinker_heartbeat);
  Blinker.attachDataStorage(blinker_dataStorage);
  btn_otcr.attach(btn_otcr_callback);
  btn_otmd.attach(btn_otmd_callback);
  btn_ottm.attach(btn_ottm_callback);
}
//Blinker心跳
void blinker_heartbeat(){
  //发送状态数据 
  num_pvp.print(system_ina_power_1);
  num_pvv.print(system_ina_voltage_1);
  num_pvc.print(system_ina_current_1);
  num_batp.print(system_ina_power_2);
  num_batv.print(system_ina_voltage_2);
  num_batc.print(system_ina_current_2);
  num_op.print(system_ina_power_3);
  num_ov.print(system_ina_voltage_3);
  num_oc.print(system_ina_current_3);
  num_tem.print(system_temperature_ntc);
  num_inwh.print(system_power_meter_in);
  num_batwh.print(system_power_meter_bat);
  num_outwh.print(system_power_meter_out);
  num_batpp.print(system_battery_percent);
  num_mpptp.print(system_mppt_efficiency);
  num_totalin.print(store_in_kwh);
  num_totalbat.print(store_bat_kwh);
  num_totalout.print(store_out_kwh);
  //发送运行状态
  blinker_msg.print(getSysInfo());
  //发送开关状态
  if(system_output_state == 0){
    btn_otcr.color("#32CD32");
    btn_otcr.text("输出开");
    btn_otcr.print("on");
  }else{
    btn_otcr.color("#D3D3D3");
    btn_otcr.text("输出关");
    btn_otcr.print("off");
  }
  //工作模式按钮状态
  switch(system_output_control_mode){
    case 0:
      btn_otmd.text("普通模式");
      break;
    case 1:
        btn_otmd.text("光控模式");
      break;
    case 2:
        btn_otmd.text("光控+时控");
      break;
  }
  btn_otmd.print();
  //光时控时间按钮状态
  btn_ottm.text(system_output_optical_control_time);
  btn_ottm.print();
}
//Blinker存储历史数据，最多6个不同的key
void blinker_dataStorage(){
  Blinker.dataStorage("ds_pvp", system_ina_power_1);
  Blinker.dataStorage("ds_pvv", system_ina_voltage_1);
  Blinker.dataStorage("ds_pvc", system_ina_current_1);
  Blinker.dataStorage("ds_bv",  system_ina_current_2);
  Blinker.dataStorage("ds_bc", system_ina_current_2);
  Blinker.dataStorage("ds_ov", system_ina_power_3);
}
//Blinker数据读取
void blinker_dataRead(const String &data){
  BLINKER_LOG("Blinker readString: ", data);

}
//Blinker按键响应
void btn_otcr_callback(const String & state){
  if (state == BLINKER_CMD_ON && system_output_control_mode==0) {
        BLINKER_LOG("Toggle on!");
        btn_otcr.color("#32CD32");
        btn_otcr.text("输出开");
        btn_otcr.print("on");
        system_output_state = 0;
    }else if (state == BLINKER_CMD_OFF) {
        BLINKER_LOG("Toggle off!");
        btn_otcr.color("#D3D3D3");
        btn_otcr.text("输出关");
        btn_otcr.print("off");
        system_output_state = 1;
    }
    Blinker.vibrate();
}
void btn_otmd_callback(const String & state){
  if (state == BLINKER_CMD_BUTTON_TAP) {
      BLINKER_LOG("Button tap!");
      system_output_control_mode>=2? system_output_control_mode = 0 : system_output_control_mode ++;
      switch(system_output_control_mode){
        case 0:
          btn_otmd.text("普通模式");
          break;
        case 1:
          btn_otmd.text("光控模式");
          break;
        case 2:
          btn_otmd.text("光控+时控");
          break;
      }
      btn_otmd.print();
      Blinker.vibrate();
  }
}
void btn_ottm_callback(const String & state){
  if (state == BLINKER_CMD_BUTTON_TAP) {
      BLINKER_LOG("Button tap!");
      system_output_optical_control_time >=12? system_output_optical_control_time = 1 : system_output_optical_control_time ++;
      btn_ottm.text(system_output_optical_control_time);
      btn_ottm.print();
      Blinker.vibrate();
  }
}

/*
MQTT
以下是mqtt代码部分
*/
void mqtt_init(){
  //连接wifi
  Serial.print(F("连接wifi:"));
  Serial.println(wifi_ssid);
  WiFi.setAutoReconnect(true);    //设置断开连接后重连
  WiFi.setSleep(false);           //禁止休眠
  WiFi.begin(wifi_ssid.c_str(), wifi_psd.c_str());
  //启动MQTT服务
  mqtt_client.setServer(mqtt_server_add.c_str(), mqtt_server_port);
  mqtt_client.setCallback(mqtt_callback);
  mqtt_client.setKeepAlive(system_mqtt_keepalive);
  //更新topic
  topic_will                 +=        sys_mac_address_pure+ "/will";                      //遗嘱
  topic_read_pvc             +=        sys_mac_address_pure+ "/pvc/value";                 //读取电压、电流、功率
  topic_read_state           +=        sys_mac_address_pure+ "/state";                     //温度读取、累计电量
  topic_command_output       +=        sys_mac_address_pure+ "/outputcontroller";          //输出开关
  topic_command_opentime     +=        sys_mac_address_pure+ "/opentime";                  //设置光控+时控模式打开时间
  topic_command_outtype      +=        sys_mac_address_pure+ "/outtype";                   //输出模式  
  topic_log                  +=        sys_mac_address_pure+ "/log";                       //错误日志
  topic_command_settings     +=        sys_mac_address_pure+ "/system/setting";            //错误日志
  //init完成，更新状态
  system_mqtt_initialized = 1;
}
//mqtt信息接收处理方法
void mqtt_callback(char* topic, byte* payload, unsigned int length) {
  Serial.print(F("收到>>"));
  Serial.print(topic);
  Serial.print(F(" : "));
  String read_buffer;
  for (int i = 0; i < length; i++) {
    read_buffer += (char)payload[i];
  }
  Serial.println(read_buffer);
  //接收控制指令
  if(strcmp(topic, topic_command_output.c_str())==0){
    if(strcmp(read_buffer.c_str(), "on")==0){
      system_output_state = 0;   //打开输出
    }else if(strcmp(read_buffer.c_str(), "off")==0){
      system_output_state = 1;   //关闭输出
    }
  }else
  if(strcmp(topic, topic_command_opentime.c_str())==0){
    int readint = atoi(read_buffer.c_str());
    if(readint>0 && readint<13){    //判断值是否在有效区间1-12之间
      system_output_optical_control_time = readint;
    }
  }else
  if(strcmp(topic, topic_command_outtype.c_str())==0){
    if(strcmp(read_buffer.c_str(), "普通模式")==0){
      system_output_control_mode = 0;
    }else if(strcmp(read_buffer.c_str(), "光控模式")==0){
      system_output_control_mode = 1;
    }else if(strcmp(read_buffer.c_str(), "光控+时控")==0){
      system_output_control_mode = 2;
    }
  }else
  if(strcmp(topic, topic_command_settings.c_str())==0){
    if(strcmp(read_buffer.c_str(), "clear_historical_data_without_saving")==0){
      store_in_kwh             = 0.0;
      store_bat_kwh            = 0.0;
      store_out_kwh            = 0.0;
      system_power_meter_in    = 0.0;
      system_power_meter_bat   = 0.0;
      system_power_meter_out   = 0.0;   
    }else if(strcmp(read_buffer.c_str(), "save_save_save_now")==0){
      store_sys_data();
    }
  }
  //发送状态
  mqtt_client.publish(topic_read_state.c_str(), MQTT_getStateMSG().c_str()); 
  mqtt_sendmsg_lastmillis = millis();
}
//重新连接方法
void mqtt_reconnect(){
  if(mqtt_reconncet_lastmillis!=0 && millis()-mqtt_reconncet_lastmillis<5000){ return;}   //连接失败，5s后重新连接
  if(system_mqtt_initialized == 0){ mqtt_init();}
  if(WiFi.status() != WL_CONNECTED) {
    WiFi.reconnect(); //重新连接wifi
    mqtt_reconncet_lastmillis = millis();
    return;
  }
  Serial.print(F("成功连接到:"));
  Serial.print(wifi_ssid);
  Serial.print(F("    IP地址: "));
  Serial.println(WiFi.localIP());
  //读取mac
  sys_ip_address = WiFi.localIP().toString();
  Serial.print(F("尝试连接MQTT服务器: "));
  Serial.print(mqtt_server_add);
  Serial.print(":");
  Serial.println(mqtt_server_port);
  String clientId = "mppt-" + sys_mac_address_pure;
  Serial.println("客户端ID: " + clientId);
  if (mqtt_client.connect(clientId.c_str(), mqtt_usr.c_str(), mqtt_psd.c_str(), topic_will.c_str(), MQTT_WILL_QOS, false, "offline")) {
    Serial.println(F("连接成功！"));
    mqtt_reconncet_lastmillis = 0;
    //发遗嘱
    mqtt_client.publish(topic_will.c_str(), "online");
    //订阅主题
    mqtt_client.subscribe(topic_command_output.c_str());
    mqtt_client.subscribe(topic_command_opentime.c_str());
    mqtt_client.subscribe(topic_command_outtype.c_str());
    mqtt_client.subscribe(topic_command_settings.c_str());
    //更新状态
    mqtt_client.publish(topic_read_state.c_str(), MQTT_getStateMSG().c_str());
  }else{
    mqtt_reconncet_lastmillis = millis();
    Serial.print(F("连接失败, rc="));
    Serial.print(mqtt_client.state());
    Serial.println(F(" 5秒后尝试重新连接"));
  }
}

//发送状态数据
void mqtt_heartbeat(){
  //mqtt数据更新发送频率
  if(millis()-mqtt_sendmsg_lastmillis < mqtt_refresh_state_delay){
    return;
  }
  mqtt_sendmsg_lastmillis = millis();
  //发遗嘱
  mqtt_client.publish(topic_will.c_str(), "online");
  //发送ina的信息
  String msg_ina = ""; 
  msg_ina += "{\"inputvoltage\":" +String(system_ina_voltage_1, 2)+ 
             ", \"inputcurrent\":" +String(system_ina_current_1, 2)+ 
             ", \"inputpower\":" +String(system_ina_power_1, 2)+ 
             ", \"batteryvoltage\":" +String(system_ina_voltage_2, 2)+ 
             ", \"batterycurrent\":" +String(system_ina_current_2, 2)+ 
             ", \"batterypower\":" +String(system_ina_power_2, 2)+ 
             ", \"outputvoltage\":" +String(system_ina_voltage_3, 2)+ 
             ", \"outputcurrent\":" +String(system_ina_current_3, 2)+ 
             ", \"outputpower\":" +String(system_ina_power_3, 2)+ "}";
  mqtt_client.publish(topic_read_pvc.c_str(), msg_ina.c_str());
  //发送状态
  mqtt_client.publish(topic_read_state.c_str(), MQTT_getStateMSG().c_str()); 
}
//获取状态信息
String MQTT_getStateMSG(){
  String system_output_state_str;
  system_output_state == 0? system_output_state_str = "on" : system_output_state_str = "off";
  String system_output_control_mode_str;
  switch(system_output_control_mode){
    case 0:
      system_output_control_mode_str = "普通模式";
      break;
    case 1:
      system_output_control_mode_str = "光控模式";
      break;
    case 2:
      system_output_control_mode_str = "光控+时控";
      break;
  }
  String msg_state = "{\"tem\":" +String(system_temperature_ntc)+                    //温度
                      ", \"batp\":" +String(system_battery_percent)+                 //电池电量%
                      ", \"inwh\":" +String(system_power_meter_in, 2)+               //输入累计功率-每日
                      ", \"batwh\":" +String(system_power_meter_bat, 2)+             //电池累计功率-每日
                      ", \"outwh\":" +String(system_power_meter_out, 2)+             //输出累计功率-每日
                      ", \"totalin\":" +String(store_in_kwh, 2)+                     //输入累计功率-历史
                      ", \"totalbat\":" +String(store_bat_kwh, 2)+                   //电池累计功率-历史
                      ", \"totalout\":" +String(store_out_kwh, 2)+                   //输出累计功率-历史
                      ", \"ostate\":\"" +system_output_state_str+ "\""+              //输出状态
                      ", \"otime\":" +String(system_output_optical_control_time)+    //光控+时控模式打开时间
                      ", \"otype\":\"" +system_output_control_mode_str+ "\""+        //输出模式
                      ", \"mppt\":" +String(system_mppt_efficiency)+                 //mppt效率%
                      "}";
  return msg_state;
}

//mqtt发送错误日志
void MQTT_send_log(String logstr){
  if(system_internet_mode==1&&mqtt_client.state()==MQTT_CONNECTED){
    mqtt_client.publish(topic_log.c_str(), logstr.c_str());
  }
}